home *** CD-ROM | disk | FTP | other *** search
- /**\
- |**| =====================================================================
- |**|
- |**| Glyph Layout.c
- |**|
- |**| This file contains the calls that this sample needs to make
- |**| the QuickDraw GX shell work correctly.
- |**|
- |**| QuickDraw GX Libraries Used:
- |**| "color library.c", "font library.c", "graphics debug library.c",
- |**| "layout library.c", "shape library.c", and "transform library.c".
- |**|
- |**| ©1992-1994 Apple Computer, Inc.
- |**| All rights reserved.
- |**|
- |**| =====================================================================
- \**/
- /****************************************************************************/
- /* */
- /* Basic Layout Sample.c */
- /* */
- /* This file contains the calls that an application needs to make */
- /* the QuickDraw GX shell work correctly. */
- /* */
- /* QuickDraw GX Libraries Used: */
- /* "color library.c", "font library.c", "graphics debug library.c", */
- /* "layout library.c", "shape library.c", and "transform library.c". */
- /* */
- /* Written by Eric Mader and Robert Dierkes */
- /* */
- /* 1.0B2 MD 09/09/93 change QDLocalToFixedGlobal to GXConvertQDPoint,*/
- /* including removing validation just for B2 */
- /* */
- /* ©1992-1994 Apple Computer, Inc. */
- /* All rights reserved. */
- /* */
- /****************************************************************************/
-
- #include "QDGX shell.h"
- #include "layout routines.h"
- #include "layout library.h"
- #include "font menu library.h"
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| PROTOTYPES
- |**| ---------------------------------------------------------------------
- \**/
-
- // funtions required by shell
-
- void DoSetup (void);
- void DoDraw (WindowPtr wind, Boolean updating);
- OSErr DoCreateNew (void);
- void DoDispose (WindowPtr wind);
- void DoIdle (WindowPtr wind);
- void DoTeardown (void);
- void DoClick (WindowPtr wind, Point p);
-
- // private functions
-
- OSErr DoWindowInit (WindowPtr wind);
- void CreateSampleImage (WindowPtr wind);
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| ENUMS
- |**| ---------------------------------------------------------------------
- \**/
- enum { rWindResource = 128, rStartOfHeirMenus=140 };
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| GLOBALS
- |**| ---------------------------------------------------------------------
- \**/
- // If gDebugging = TRUE, graphics library errors and notices will be posted. This
- // functionality will only work with the "debugging" version of QuickDraw GX.
- // If the debugging version is not installed, nothing bad will happen, but these
- // functions will not work.
-
- Boolean gDebugging = true;
-
- // Set "gGiveMeValidation" to TRUE if you want receive run-time validation.
-
- Boolean gGiveMeValidation = true;
-
-
- // gGraphicsHeapSize sets the size of the graphics heap created by calling the
- // GXNewGraphicsClient routine in main () within QuickDraw GX shell.c. You can determine
- // the amount of graphics heap required by using GraphicsBug. I'm giving it 600K,
- // since we need abunch if we have several windows open.
-
- long gGraphicsHeapSize = 600;
-
- // gOurPrintingOverrideUPP is a universal proc pointer for our printing event
- // override. This is so that our override can be native PowerPC code if necessary.
-
- GXPrintingEventUPP gOurPrintingOverrideUPP;
-
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoSetup()
- |**| Here's where we initialize any global variables our application needs.
- |**| We have only one at this time -- the universal proc pointer for
- |**| our printing override.
- |**| ---------------------------------------------------------------------
- \**/
- void DoSetup (void)
- { // Initialize our printing event override UPP
- gOurPrintingOverrideUPP = NewGXPrintingEventProc(MyPrintingEventOverride);
-
- EnableItem(GetMHandle(mEdit), 0);
- DisableItem(GetMHandle(mEdit), iUndo);
- EnableItem(GetMHandle(mEdit), iCut);
- EnableItem(GetMHandle(mEdit), iCopy);
- EnableItem(GetMHandle(mEdit), iPaste);
- EnableItem(GetMHandle(mEdit), iClear);
-
- HierFontMenu( GetMHandle(fontMenuID),
- rStartOfHeirMenus,
- (fontFilterProc) nil,
- noInstancesFontMenu);
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoDraw()
- |**| Draw the contents of the window. The first parameter is the window
- |**| to draw, and the second parameter is true if we're updating an existing
- |**| image. If that's the case, we don't want to change anything, but
- |**| just draw what's already there.
- |**| ---------------------------------------------------------------------
- \**/
- void DoDraw (WindowPtr wind, Boolean updating)
- {
- #pragma unused (updating)
- // GXDrawShape (GetDocShape(wind));
- LayoutEditUpdate( GetDocLEHandle(wind) );
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoCreateNew()
- |**| This routine is called when a window needs to be created.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoCreateNew (void)
- {
- OSErr err = noErr;
- WindowPtr wind;
-
- // Get and create our window from the resource fork
-
- wind = GetNewWindow(rWindResource, nil, (WindowPtr)-1L);
-
- // Attach a default gxViewPort to it, create and iInitialize our
- // private data for it, and add a sample image to its page shape.
-
- if ( wind == NULL )
- return (MemError());
-
- GXIgnoreGraphicsNotice(transform_already_set);
- SetDefaultViewPort(GXNewWindowViewPort(wind));
- GXPopGraphicsNotice();
-
- err = DoWindowInit(wind);
- if ( err != noErr )
- return err;
-
- CreateSampleImage(wind);
- return err;
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoDispose()
- |**| This routine is called when a window needs to be disposed of.
- |**| ---------------------------------------------------------------------
- \**/
- void DoDispose (WindowPtr wind)
- {
- TH_Doc doc;
-
- // You should always dispose of your GX graphics objects before tossing your window.
- // Why? It's generally good form and this approach guarantees that everything is
- // disposed. If you had not disposed of everything, the call to DisposeWindow should
- // dispose of the objects. If you are running the debugging version of QuickDraw GX
- // with notices set, you will receive a notice that you had not disposed of everything.
- // You can turn notices on in this file by setting gDebugging = TRUE (above).
-
- if ( wind != NULL )
- {
- doc = (TH_Doc)GetWRefCon(wind); // Remember, this is where we stored our private data.
- GXDisposeShape(GetDocShape(wind)); // Dispose of this doc's shape.
- GXDisposeJob(GetDocJob(wind)); // Dispose of this doc's print job.
- DisposHandle((Handle) doc); // Dispose of our private data.
- DisposeWindow(wind); // Dispose of the window.
- }
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoIdle()
- |**| This routine is called to do things while idling through the event loop.
- |**| ---------------------------------------------------------------------
- \**/
- void DoIdle (WindowPtr wind)
- {
- LayoutEditIdle( GetDocLEHandle(wind) );
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoTeardown()
- |**| This routine is called just before we quit to remove anything
- |**| persistent that might have been setup by DoSetup().
- |**| ---------------------------------------------------------------------
- \**/
- void DoTeardown (void)
- {
- DisposeRoutineDescriptor(gOurPrintingOverrideUPP);
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoClick()
- |**| ---------------------------------------------------------------------
- \**/
- void DoClick(WindowPtr window, Point p)
- {
- gxPoint hitDown;
- gxValidationLevel currentValidation;
-
- // Unfortunately, GXConvertQDPoint(..) will not survive validation with the QD GX ß2
- // seed. Therefore, we get the validation level set up by the application, and turn the
- // validation off. We will reset the validation to it's original setting below.
- //
- // This problem has already been fixed in the QD GX ß3 build, therefore this work around
- // will be removed at ß3. Details about the parameters for the GXConvertQDPoint (..) call
- // can be found in the QD GX ß2 Graphics Notes within the "• Open Me First •" folder.
-
- currentValidation = GXGetValidation();
- if (currentValidation) GXSetValidation(gxNoValidation);
-
- /** Convert the global Quickdraw coordinates to local fixed coordinates. **/
- GXConvertQDPoint(&p, 0, &hitDown);
-
-
- // Reset the validation to the original setting.
-
- if (currentValidation) GXSetValidation(currentValidation);
-
- LayoutEditClick( GetDocLEHandle(window), hitDown);
- }
-
-
-
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoWindowInit()
- |**| In this function we create and initialize the the private document
- |**| structure for a new window. This structure contains the print job and
- |**| the shape which is drawn in the window. We store this data in a handle
- |**| and hang it off the window's refCon field for easy retrieval. By doing
- |**| this, rather than using globals, we can create many windows containing
- |**| unique print jobs and shapes.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoWindowInit (WindowPtr wind)
- {
- OSErr err = noErr;
- gxJob docJob;
- gxShape docPage;
- gxShape docErase;
- TH_Doc windDoc;
-
-
- // Create the page shape. We set the unique items attribute to make sure that each item
- // added to the picture has a unique reference. If this attribute was not set, we would
- // not see all copies of anything we add to the shape multiple times -- we'd just see
- // the last version added.
-
- docPage = GXNewShape(gxPictureType);
- GXSetShapeAttributes(docPage, (GXGetShapeAttributes(docPage) | gxUniqueItemsShape));
-
-
- // Create the erase shape. We set the unique items attribute to make sure that each item
- // added to the picture has a unique reference. If this attribute was not set, we would
- // not see all copies of anything we add to the shape multiple times -- we'd just see
- // the last version added.
-
- docErase = GXNewShape(gxPictureType);
- GXSetShapeAttributes(docErase, (GXGetShapeAttributes(docErase) | gxUniqueItemsShape));
-
-
- // Create a print job for this document. This will be the same as the system default until
- // the user goes through the dialogs for Page Setup or Print…
-
- err = GXNewJob(&docJob);
-
-
- // If there are no errors, create a handle the size of our document structure and store
- // the print job and page shape in it. Store the handle in the window's refCon field so
- // that we can get at it. (Note that the utility routines "GetDocJob" and "GetDocShape"
- // can be used to do this easily.
-
- if ( err == noErr )
- {
- windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
-
- if ( windDoc == NULL )
- err = MemError();
- else
- {
- (*windDoc)->docJob = docJob;
- (*windDoc)->docPage = docPage;
- (*windDoc)->docLEHandle = nil;
- SetWRefCon(wind, (long) windDoc);
- }
-
- // Now install our application override for PrintingEvent so that we can
- // support the new movable-modal printing dialog boxes.
-
- GXInstallApplicationOverride(docJob, gxPrintingEvent, gOurPrintingOverrideUPP);
-
- }
-
- return err;
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| CreateSampleImage()
- |**| This function creates primitive shapes and adds them to the window's page shape.
- |**| ---------------------------------------------------------------------
- \**/
- void CreateSampleImage (WindowPtr wind)
- {
- Rect ourWindowRect = wind->portRect; // the rectangle for this window
- // in QuickDraw coordinates
- gxShape layout; // the layout shape we build
- gxShape thePage; // this window's document shape
- gxRunControls runControls; // run controls for the layout shape
- gxLayoutOptions layoutOptions; // options for the layout shape
- gxStyle timesStyle; // a style record for a Times-based style
- gxStyle hoeflerStyle; // ditto for Helvetica
- gxStyle baghdadStyle; // ditto for Baghdad
- gxStyle textStyles[4]; // an array of text style for our text runs
-
- // These are the five text runs for this layout shape, in pieces because they're
- // in different languages
-
- char *text1 = "The wicked ";
- char *text2 = "fast ";
-
- // The following is "Macintosh" in Arabic:
- // meem, alif, kaf, noon, tah, wau, shin
- // (This assumes the standard Arabic character set for Macintosh, by the way)
-
- static char text3[] = {0xE5, 0xC7, 0xE3, 0xE6, 0xCA, 0xE8, 0xD4, 0};
-
- char *text4 = " lives!";
-
-
- char *textRuns[4]; // an array of pointers to text runs
-
- short textLengths[4]; // an array of the lengths of each run
- short totalLength; // the total length of the layout's text
- // static short levelRunLengths[3]; // an array of the lengths of each level
- // static short levels[3] = {0, 1, 0}; // the level numbers for each level
- short levels = 0;
-
- gxPoint posn; // the position of the layout shape
-
-
- // First, initialize the textRuns array to point to the five text runs
-
- textRuns[0] = text1;
- textRuns[1] = text2;
- textRuns[2] = text3;
- textRuns[3] = text4;
-
-
- // Initialize the text lengths.
-
- textLengths[0] = MyStrLength(text1);
- textLengths[1] = MyStrLength(text2);
- textLengths[2] = MyStrLength(text3);
- textLengths[3] = MyStrLength(text4);
-
- // Our layout has three levels in it -- level 0 for the English runs at each end,
- // and level 1 for the Arabic text in the middle. We need the byte-count for each
- // level's text run in the levelRunLengths array.
-
- // levelRunLengths[0] = textLengths[0];
- // levelRunLengths[1] = textLengths[1] + textLengths[2] + textLengths[3];
- // levelRunLengths[2] = textLengths[4];
-
-
- // totalLength is the length of all the text.
-
- totalLength = textLengths[0] + textLengths[1] + textLengths[2] + textLengths[3];
-
-
- // make default gxLayoutOptions and gxRunControls structures
-
- InitializeLayoutOptions (&layoutOptions);
- InitializeRunControls (&runControls);
-
- // Position the layout half way down the left edge of the window. Set
- // the layout's width to the window's width and set the flushness to 1/2, this
- // will cause the layout to center in the window. Note that ourWindowRect is
- // not in fixed coordinates, so we have to make it fixed to use it.
-
- layoutOptions.width = ff(ourWindowRect.right - ourWindowRect.left);
- layoutOptions.flush = fract1/2;
-
- posn.x = 0;
- posn.y = ff((ourWindowRect.bottom - ourWindowRect.top) / 2);
-
-
- // Create the styles we'll use. The helveticaStyle is 30-point Helvetica.
- // NewLayoutStyle is a library routine found in layout library.c. But first,
- // this important message:
-
- // When I was converting this sample to actually print, I found this strange
- // problem that the highlight shape, while appearing correctly on the screen,
- // was always too far to the right when printed -- sometimes overlapping parts
- // of glyphs that shouldn't be highlighted. An investigation was launched.
- //
- // It turns out that highlight shapes are pretty much always 72 DPI, because
- // they're polygons calculated from the metrics of the layout shape when the
- // highlight shape is created. If you then scale the layout shape by
- // transforming it to 300 DPI or so (like a printer driver would do), the
- // highlight shape has the same geometry while hinting of the glyphs may have
- // changed the way the layout shape looks. They've moved a little bit, perhaps,
- // and therefore the highlight shape isn't in the right place anymore.
- //
- // If this is for your on-screen work, you can recreate the highlight shape in
- // a zoomed viewPort, but you don't get to make the printer driver do that for
- // you. So, instead, for each style run we use, we add the gxNoMetricsGridText
- // attribute. This prevents QuickDraw GX from using hinting, so the glyphs always
- // scale the same way the highlight shape does, and all is well.
- //
- // (At first, I tried to fix this by adding gxNoMetricsGridShape to the layout
- // _shape's_ attributes, but that's not the right idea. The attributes in the
- // shape's style affect any part of the layout that doesn't have a style of its
- // own, including any parts of the text for which the entry in the style array
- // is nil. Since we're actually applying styles over the layout here, the
- // gxNoMetricsGridText must be set in those styles, not in the shape's style.)
- //
- // This does mean that your glyphs won't get hinting at low resolutions and
- // small point sizes where it might be desirable -- but it's really only a problem
- // if you're trying to print a highlight shape, which doesn't happen very often.
- // In fact, I can't really think of a legitimate reason to want to do it, except
- // maybe in sample code.
-
- hoeflerStyle = NewLayoutStyle(
- (char *) "\pHoefler Text", // the gxFontName for the style
- ff(30), // the text size in fixed point
- gxNoMetricsGridText, // gxTextAttributes
- &runControls, // run controls (our default ones)
- nil, // run features (none for this style)
- 0, // count of run features
- nil); // style run overrides (none right now)
-
- // The second style is baghdadStyle -- Baghdad Plain (Arabic), 30 points.
-
- baghdadStyle = NewLayoutStyle(
- (char *) "\pBaghdad Plain", // gxFontName
- ff(30), // text size (fixed point)
- gxNoMetricsGridText, // gxTextAttributes
- &runControls, // run controls (our default ones)
- nil, // run features (none)
- 0, // count of run features (none)
- nil); // style run overrides (none)
-
- // The final style is 30-point Times Roman.
-
- timesStyle = NewLayoutStyle(
- (char *) "\pTimes Roman", // gxFontName
- ff(30), // text size (fixed point)
- gxNoMetricsGridText, // gxTextAttributes
- &runControls, // run controls (our default ones)
- nil, // run features (none)
- 0, // count of run features (none)
- nil); // style run overrides (none)
-
-
- // Initialize the textStyles array so that each of the five runs has the right style
-
- textStyles[0] = hoeflerStyle;
- textStyles[1] = timesStyle;
- textStyles[2] = baghdadStyle;
- textStyles[3] = hoeflerStyle;
-
-
- // Setup complete! Build the layout.
-
- layout = GXNewLayout(
- 4, // count of text runs
- textLengths, // array of lengths of each run
- (void *) textRuns, // array of pointers to the text
- 4, // count of style runs
- textLengths, // array of the byte lengths of each run
- textStyles, // array of the styles
- 1, // number of levels in the layout
- &totalLength, // array of the lengths of each level
- &levels, // array of the levels
- &layoutOptions, // options (default)
- &posn); // position of the layout shape
-
- GXSetShapeStyle(layout, hoeflerStyle);
-
-
-
- // Retrieve the page shape so we can add to it.
-
- thePage = GetDocShape(wind);
-
- // Add the layout to the window's picture shape. AddToShape is in shape library.c.
-
- AddToShape(thePage, layout);
-
-
- // build LayoutEditHandle and attatch to this windows document
- // layoutHandle = LayoutEditHandleFromLayout(layout);
- if ( wind != NULL )
- {
- TH_Doc doc = (TH_Doc) GetWRefCon(wind);
- (*doc)->docLEHandle = LayoutEditHandleFromLayout(layout);
- }
-
-
- // Dispose of what we allocated
-
- // GXDisposeShape(layout);
- GXDisposeStyle(hoeflerStyle);
- GXDisposeStyle(baghdadStyle);
- GXDisposeStyle(timesStyle);
-
-
- // Invalidate the window's portRect so that everything gets updated.
-
- SetPort(wind);
- InvalRect(&ourWindowRect);
- }
-
-